package com.esd.device.controller;

import com.esd.common.pojo.R;
import com.esd.device.entity.ChannelType;
import com.esd.device.entity.EsdLog;
import com.esd.device.entity.Line;
import com.esd.device.service.ChannelTypeService;
import com.esd.device.service.DeviceService;
import com.esd.device.service.EsdLogService;
import com.esd.device.service.LineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;

@RestController
@RequestMapping("esdLog")
public class EsdLogController {

    @Autowired
    private EsdLogService esdLogService ;

    @Autowired
    private LineService lineService ;
    @GetMapping("errorCountBar/{type}")
    public R errorCountBar(@PathVariable Integer type){
        List<EsdLog> esdLogs = esdLogService.getEsdLogByTime(type , "异常");
        List<Line> lines = lineService.list();
        List<String> lineNames = new ArrayList<>();
        Map<String , Integer> map = new HashMap<>();
        lines.forEach(line -> {
            lineNames.add(line.getLineName());
            map.put(line.getLineName() , 0) ;
        });
        esdLogs.forEach(esdLog -> {
            if(map.containsKey(esdLog.getLine())){
                map.put(esdLog.getLine(), map.get(esdLog.getLine()) + 1);
            }
        });
        List<Integer> timesList = new ArrayList<>() ;
        lineNames.forEach( lineName ->{
            timesList.add(map.get(lineName));
        });
        Map<String , Object> resultMap = new HashMap<>();
        resultMap.put("lineNames" , lineNames);
        resultMap.put("timesList" , timesList);
        return R.ok(resultMap);
    }

    @Autowired
    private DeviceService deviceService ;

    @GetMapping("getStatisticsData")
    public R getStatisticsData(){
        return deviceService.getStatisticsData() ;
    }

    @GetMapping("getUnNormalData")
    public R getUnNormalData(){
        return deviceService.getUnNormalData() ;
    }

    @GetMapping("errorTimeBar/{type}")
    public R errorTimeBar(@PathVariable Integer type){
        List<EsdLog> esdLogs = esdLogService.getEsdLogByTime(type , "异常");
        List<Line> lines = lineService.list();
        List<String> lineNames = new ArrayList<>();
        Map<String , Long> map = new HashMap<>();
        lines.forEach(line -> {
            lineNames.add(line.getLineName());
            map.put(line.getLineName() , 0L) ;
        });
        esdLogs.forEach(esdLog -> {
            if(map.containsKey(esdLog.getLine())){
                LocalDateTime endTime = esdLog.getEndTime();
                if (endTime != null){
                    long time = endTime.toEpochSecond(ZoneOffset.ofHours(8)) - esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                    map.put(esdLog.getLine(), map.get(esdLog.getLine()) + time);
                }else {
                    LocalDateTime now = LocalDateTime.now();
                    long time = now.toEpochSecond(ZoneOffset.ofHours(8)) - esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                    map.put(esdLog.getLine(), map.get(esdLog.getLine()) + time);
                }
            }
        });
        List<BigDecimal> timeList = new ArrayList<>() ;
        lineNames.forEach( lineName ->{
            // 四舍五入， 保留两位小数
            timeList.add(new BigDecimal(map.get(lineName)).divide(new BigDecimal(60) , 2, RoundingMode.HALF_UP));
        });
        Map<String , Object> resultMap = new HashMap<>();
        resultMap.put("lineNames" , lineNames);
        resultMap.put("timeList" , timeList);
        return R.ok(resultMap);
    }

    @Autowired
    private ChannelTypeService channelTypeService ;
    @GetMapping("typeStableBar/{type}")
    public R typeStableBar(@PathVariable Integer type){
        List<ChannelType> channelTypes = channelTypeService.list();
        List<String> channelTypeNames = new ArrayList<>();
        Map<String , BigDecimal> map = new HashMap<>();
        channelTypes.forEach(channelType -> {
            channelTypeNames.add(channelType.getChannelTypeName());
            List<EsdLog> errorList = esdLogService.getEsdLogByTimeAndChanneType(
                    type, "异常", channelType.getChannelTypeName());
            List<EsdLog> normalList = esdLogService.getEsdLogByTimeAndChanneType(
                    type, "正常", channelType.getChannelTypeName());
            List<EsdLog> standByList = esdLogService.getEsdLogByTimeAndChanneType(
                    type, "待机", channelType.getChannelTypeName());
            if (errorList.isEmpty() && normalList.isEmpty() && standByList.isEmpty()) {
                map.put(channelType.getChannelTypeName() , new BigDecimal(100));
            }else {
                map.put(
                    channelType.getChannelTypeName() ,
                        getPercents(errorList , normalList , standByList)) ;
            }
        });
        List<BigDecimal> percents = new ArrayList<>() ;
        channelTypeNames.forEach( channelTypeName ->{
            // 四舍五入， 保留两位小数
            percents.add(map.get(channelTypeName));
        });
        return R.ok(sortData(channelTypeNames , percents));
    }

    @GetMapping("lineStableBar/{type}")
    public R lineStableBar(@PathVariable Integer type){
//        List<Line> lines = lineService.selectAllHasDevice();
        List<Line> lines = lineService.list();
        List<String> lineNames = new ArrayList<>();
        Map<String , BigDecimal> map = new HashMap<>();
        lines.forEach(line -> {
            lineNames.add(line.getLineName());
            List<EsdLog> errorList = esdLogService.getEsdLogByTimeAndLine(
                    type, "异常", line.getLineName());
            List<EsdLog> normalList = esdLogService.getEsdLogByTimeAndLine(
                    type, "正常", line.getLineName());
            List<EsdLog> standByList = esdLogService.getEsdLogByTimeAndLine(
                    type, "待机", line.getLineName());
            if (errorList.isEmpty() && normalList.isEmpty() && standByList.isEmpty()) {
                map.put(line.getLineName() , new BigDecimal(100));
            }else {
                map.put(
                        line.getLineName() ,
                        getPercents(errorList , normalList , standByList)) ;
            }
        });
        List<BigDecimal> percents = new ArrayList<>() ;
        lineNames.forEach( lineName ->{
            // 四舍五入， 保留两位小数
            percents.add(map.get(lineName));
        });

        return R.ok(sortData(lineNames , percents));
    }

    private BigDecimal getPercents(
            List<EsdLog> errorList ,
            List<EsdLog> normalList ,
            List<EsdLog> standByList){
        final long[] totalTimes = {0L};
        final long[] errorTimes = {0L} ;
        errorList.forEach(esdLog -> {
            LocalDateTime endTime = esdLog.getEndTime();
            if (endTime != null){
                long time = endTime.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
                errorTimes[0] += time ;
            }else {
                LocalDateTime now = LocalDateTime.now();
                long time = now.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
                errorTimes[0] += time ;
            }
        });
        normalList.forEach(esdLog -> {
            LocalDateTime endTime = esdLog.getEndTime();
            if (endTime != null){
                long time = endTime.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
            }else {
                LocalDateTime now = LocalDateTime.now();
                long time = now.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
            }
        });
        standByList.forEach(esdLog -> {
            LocalDateTime endTime = esdLog.getEndTime();
            if (endTime != null){
                long time = endTime.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
            }else {
                LocalDateTime now = LocalDateTime.now();
                long time = now.toEpochSecond(
                        ZoneOffset.ofHours(8)) -
                        esdLog.getStartTime().toEpochSecond(ZoneOffset.ofHours(8));
                totalTimes[0] += time;
            }
        });
        if (totalTimes[0] == 0){
            return new BigDecimal(0) ;
        }
        return  new BigDecimal(totalTimes[0] - errorTimes[0])
                .divide(new BigDecimal(totalTimes[0]), 4, RoundingMode.HALF_UP)
                .multiply(new BigDecimal(100));
    }

    private HashMap<String,Object> sortData(List<String> list , List<BigDecimal> decimals){

        if (list.size() != decimals.size()){
            return null ;
        }else {
            HashMap<String,Object> resultMap = new HashMap<>();
            String [] list1 = list.toArray(new String[0]);
            BigDecimal [] decimals1 = decimals.toArray(new BigDecimal[0]);
            for (int i = 0; i < list1.length - 1; i++) {
                for (int j = 0; j < list1.length - i - 1; j++) {
                    if (decimals1[j].compareTo(decimals1[j + 1])< 0 ) {
                        // 交换 arr[j+1] 和 arr[j]
                        BigDecimal temp = decimals1[j];
                        decimals1[j] = decimals1[j+1];
                        decimals1[j+1] = temp;

                        String temp1 = list1[j];
                        list1[j] = list1[j+1];
                        list1[j+1] = temp1;
                    }
                }
            }
            List<String> stringList = Arrays.asList(list1);
            List<BigDecimal> decimalList = Arrays.asList(decimals1);
            resultMap.put("names" , stringList);
            resultMap.put("percents" , decimalList);
            return resultMap;
        }
    }
}
